home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / amiga / asrc29k.lha / cmdparse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-08  |  6.1 KB  |  316 lines

  1. /* Parse command line, set up command arguments Unix-style, and call function.
  2.  * Note: argument is modified (delimiters are overwritten with nulls)
  3.  * Improved error handling by Brian Boesch of Stanford University
  4.  */
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include "global.h"
  8. #include "cmdparse.h"
  9. #include "proc.h"
  10.  
  11. struct boolcmd {
  12.     char *str;    /* Token */
  13.     int val;    /* Value */
  14. };
  15.  
  16. static struct boolcmd Boolcmds[] = {
  17.     "y",        1,    /* Synonyms for "true" */
  18.     "yes",        1,
  19.     "true",        1,
  20.     "on",        1,
  21.     "1",        1,
  22.     "set",        1,
  23.     "enable",    1,
  24.  
  25.     "n",        0,    /* Synonyms for "false" */
  26.     "no",        0,
  27.     "false",    0,
  28.     "off",        0,
  29.     "0",        0,
  30.     "clear",    0,
  31.     "disable",    0,
  32.     NULLCHAR
  33. };
  34.  
  35. int cmdparse(cmds,line,p)
  36. struct cmds cmds[];
  37. register char *line;
  38. void *p;
  39. {
  40.     struct cmds *cmdp;
  41.     char *argv[NARG],*cp;
  42.     char **pargv;
  43.     int argc,qflag,i;
  44.  
  45.     /* Remove cr/lf */
  46.     rip(line);
  47.  
  48.     for(argc = 0;argc < NARG;argc++)
  49.         argv[argc] = NULLCHAR;
  50.  
  51.     for(argc = 0;argc < NARG;){
  52.         qflag = 0;
  53.         /* Skip leading white space */
  54.         while(*line == ' ' || *line == '\t')
  55.             line++;
  56.         if(*line == '\0')
  57.             break;
  58.         /* Check for quoted token */
  59.         if(*line == '"'){
  60.             line++;    /* Suppress quote */
  61.             qflag = 1;
  62.         }
  63.         argv[argc++] = line;    /* Beginning of token */
  64.         /* Find terminating delimiter */
  65.         if(qflag){
  66.             /* Find quote, it must be present */
  67.             if((line = strchr(line,'"')) == NULLCHAR){
  68.                 return -1;
  69.             }
  70.             *line++ = '\0';
  71.         } else {
  72.             /* Find space or tab. If not present,
  73.              * then we've already found the last
  74.              * token.
  75.              */
  76.             if((cp = strchr(line,' ')) == NULLCHAR
  77.              && (cp = strchr(line,'\t')) == NULLCHAR){
  78.                 break;
  79.             }
  80.             *cp++ = '\0';
  81.             line = cp;
  82.         }
  83.     }
  84.     if (argc < 1) {        /* empty command line */
  85.         argc = 1;
  86.         argv[0] = "";
  87.     }
  88.     /* Lines beginning with "#" are comments */
  89.     if(argv[0] == NULLCHAR || argv[0][0] == '#')
  90.         return 0;
  91.  
  92.     /* Look up command in table; prefix matches are OK */
  93.     for(cmdp = cmds;cmdp->name != NULLCHAR;cmdp++){
  94.         if(strncmp(argv[0],cmdp->name,strlen(argv[0])) == 0)
  95.             break;
  96.     }
  97.     if(cmdp->name == NULLCHAR) {
  98.         if(cmdp->argc_errmsg != NULLCHAR) 
  99.             tprintf("%s\n",cmdp->argc_errmsg);
  100.         return -1;
  101.     } else {
  102.         if(argc < cmdp->argcmin) {
  103.             /* Insufficient arguments */
  104.             tprintf("Usage: %s\n",cmdp->argc_errmsg);
  105.             return -1;
  106.         } else {
  107.             if(cmdp->stksize == 0){
  108.                 return (*cmdp->func)(argc,argv,p);
  109.             } else {
  110.                 /* Make private copy of argv and args,
  111.                  * spawn off subprocess and return.
  112.                  */
  113.                 pargv = (char **)callocw(argc,sizeof(char *));
  114.                 for(i=0;i<argc;i++)
  115.                     pargv[i] = strdup(argv[i]);
  116.                 newproc(cmdp->name,cmdp->stksize,
  117.                 (void (*)())cmdp->func,argc,pargv,p);
  118.                 return(0);
  119.             }
  120.         }
  121.     }
  122. }
  123.  
  124. /* Call a subcommand based on the first token in an already-parsed line */
  125. int subcmd(tab,argc,argv,p)
  126. struct cmds tab[];
  127. int argc;
  128. char *argv[];
  129. void *p;
  130. {
  131.     register struct cmds *cmdp;
  132.     char **pargv;
  133.     int found = 0;
  134.     int i;
  135.  
  136.     /* Strip off first token and pass rest of line to subcommand */
  137.     if (argc < 2) {
  138.         if (argc < 1)
  139.             tprintf("SUBCMD - Don't know what to do?\n");
  140.         else
  141.             tprintf("\"%s\" - takes at least one argument\n",argv[0]);
  142.         return -1;
  143.     }
  144.     argc--;
  145.     argv++;
  146.     for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++){
  147.         if(strncmp(argv[0],cmdp->name,strlen(argv[0])) == 0){
  148.             found = 1;
  149.             break;
  150.         }
  151.     }
  152.     if(!found){
  153.         char buf[77];
  154.         memset(buf,' ',sizeof(buf));
  155.         buf[75] = '\n';
  156.         buf[76] = '\0';
  157.         tprintf("valid subcommands:\n");
  158.         for(i = 0, cmdp = tab; cmdp->name != NULLCHAR; cmdp++, i = (i+1)%5) {
  159.             strncpy(&buf[i*15],cmdp->name,strlen(cmdp->name));
  160.             if(i == 4){
  161.                 tprintf(buf);
  162.                 memset(buf,' ',sizeof(buf));
  163.                 buf[75] = '\n';
  164.                 buf[76] = '\0';
  165.             }
  166.         }
  167.         if(i != 0)
  168.             tprintf(buf);
  169.         return -1;
  170.     }
  171.     if(argc < cmdp->argcmin){
  172.         if(cmdp->argc_errmsg != NULLCHAR)
  173.             tprintf("Usage: %s\n",cmdp->argc_errmsg);
  174.         return -1;
  175.     }
  176.     if(cmdp->stksize == 0){
  177.         return (*cmdp->func)(argc,argv,p);
  178.     } else {
  179.         /* Make private copy of argv and args */
  180.         pargv = (char **)callocw(argc,sizeof(char *));
  181.         for(i=0;i<argc;i++)
  182.             pargv[i] = strdup(argv[i]);
  183.         newproc(cmdp->name,cmdp->stksize,
  184.          (void (*)())cmdp->func,argc,pargv,p);
  185.         return(0);
  186.     }
  187. }
  188.  
  189. /* Must be called by all command processes before they exit */
  190. void freeargs(argc,argv)
  191. int argc;
  192. char *argv[];
  193. {
  194.     char **pargv;
  195.  
  196.     pargv = argv;
  197.     while(argc-- != 0)
  198.         free(*argv++);
  199.     free(pargv);
  200. }
  201.  
  202. /* Subroutine for setting and displaying boolean flags */
  203. int setbool(var,label,argc,argv)
  204. int *var;
  205. char *label;
  206. int argc;
  207. char *argv[];
  208. {
  209.     struct boolcmd *bc;
  210.  
  211.     if(argc < 2){
  212.         tprintf("%s: %s\n",label,*var ? "on":"off");
  213.         return 0;
  214.     }
  215.     for(bc = Boolcmds;bc->str != NULLCHAR;bc++){
  216.         if(strcmpi(argv[1],bc->str) == 0){
  217.             *var = bc->val;
  218.             return 0;
  219.         }
  220.     }
  221.     tprintf("Valid options:");
  222.     for(bc = Boolcmds;bc->str != NULLCHAR;bc++)
  223.         if(tprintf(" %s",bc->str) == EOF)
  224.             return 1;
  225.     tprintf("\n");
  226.     return 1;
  227. }
  228.  
  229. /* Subroutine for setting and displaying long variables */
  230. int setlong(var,label,argc,argv)
  231. long *var;
  232. char *label;
  233. int argc;
  234. char *argv[];
  235. {
  236.     if(argc < 2)
  237.         tprintf("%s: %ld\n",label,*var);
  238.     else
  239.         *var = atol(argv[1]);
  240.  
  241.     return 0;
  242. }
  243.  
  244. /* Subroutine for setting and displaying short variables */
  245. int setshort(var,label,argc,argv)
  246. unsigned short *var;
  247. char *label;
  248. int argc;
  249. char *argv[];
  250. {
  251.     if(argc < 2)
  252.         tprintf("%s: %u\n",label,*var);
  253.     else
  254.         *var = atoi(argv[1]);
  255.  
  256.     return 0;
  257. }
  258.  
  259. /* Subroutine for setting and displaying integer variables */
  260. int setint(var,label,argc,argv)
  261. int *var;
  262. char *label;
  263. int argc;
  264. char *argv[];
  265. {
  266.     if(argc < 2){
  267.         tprintf("%s: %i\n",label,*var);
  268.         return 1;
  269.     } else {
  270.         *var = atoi(argv[1]);
  271.         return 0;
  272.     }
  273.  
  274. }
  275.  
  276. /* Subroutine for setting and displaying int variables (with range check) */
  277. int setintrc(var, label, argc, argv, minval, maxval)
  278. int16 *var;
  279. char *label;
  280. int argc;
  281. char *argv[];
  282. int minval;
  283. int16 maxval;
  284. {
  285.     int tmp;
  286.  
  287.     if (argc < 2)
  288.         tprintf("%s: %u\n", label, *var);
  289.     else {
  290.         tmp = atoi(argv[1]);
  291.         if (isalpha(*argv[1]) || tmp < minval || tmp > maxval) {
  292.             tprintf("%s must be %i..%i\n", label, minval, maxval);
  293.             return 1;
  294.         }
  295.         *var = (int16)tmp;
  296.     }
  297.     return 0;
  298. }
  299.  
  300. /* Subroutine for setting and displaying unsigned integer variables */
  301. int setuns(var,label,argc,argv)
  302. unsigned *var;
  303. char *label;
  304. int argc;
  305. char *argv[];
  306. {
  307.     if(argc < 2){
  308.         tprintf("%s: %u\n",label,*var);
  309.         return 1;
  310.     } else {
  311.         *var = atoi(argv[1]);
  312.         return 0;
  313.     }
  314. }
  315.  
  316.